<script setup lang="ts">
import { getDeptTree, GetNameList } from '@/api/unit/unit'
import { GetName } from '@/api/base/company'
import { propTypes } from '@/utils/propTypes'
import { ref, unref, watch } from 'vue'

import { useUserStoreWithOut } from '@/store/modules/user'
import { deptSelectEvent } from '../types'
import { joinStr } from '@/utils'

const chioseKey = ref<string[] | string | null>(null)
const depts = ref<any[]>([])
const deptName = ref<string[]>([])
const userStore = useUserStoreWithOut()
const emit = defineEmits(['change', 'load', 'update:modelValue'])
const defProps = {
  key: 'Id',
  label: 'Name',
  children: 'Children'
}
let comId: string | null = null
let deptCache = {}
const checkstrictly = ref(false)
const props = defineProps({
  renderAfterExpand: propTypes.bool.def(false),
  clearable: propTypes.bool.def(true),
  placeholder: propTypes.string.def('选择部门'),
  isUnit: propTypes.bool.def(undefined),
  status: propTypes.arrayOf(propTypes.number).def([1]),
  companyId: propTypes.string,
  modelValue: propTypes.any,
  readonly: propTypes.bool.def(false),
  disabled: propTypes.bool.def(false),
  isMultiple: propTypes.bool.def(false),
  isChioseEnd: propTypes.bool.def(false),
  isChioseUnit: propTypes.bool.def(false),
  unitId: propTypes.string,
  isFill: propTypes.bool.def(true),
  isDept: propTypes.bool.def(undefined),
  labelField: propTypes.string,
  source: propTypes.object
})
const loadName = async (keys) => {
  deptName.value = await GetNameList(keys)
}
const format = (row) => {
  if (row.IsUnit && !props.isChioseUnit) {
    row.disabled = true
  } else {
    row.disabled = row.IsFill
  }
  if (row.Children.length === 0) {
    row.Children = null
  } else {
    row.Children.forEach((c) => {
      deptCache[c.Id] = c
      format(c)
    })
  }
}
const loadTree = async () => {
  const res = await getDeptTree({
    CompanyId: comId,
    Status: props.status,
    UnitId: props.unitId,
    IsUnit: props.isUnit,
    IsDept: props.isDept,
    IsFill: props.isFill
  })
  deptCache = {}
  if (res && res.length > 0) {
    res.forEach((c) => {
      deptCache[c.Id] = c
      format(c)
    })
    depts.value = res
  } else {
    depts.value = []
  }
  refreshLabel()
}
const refreshLabel = () => {
  if (props.source == null || props.labelField == null) {
    return
  } else if (props.readonly) {
    unref(props.source)[props.labelField] = unref(deptName)?.join(',')
  } else if (chioseKey.value == null || chioseKey.value.length === 0) {
    unref(props.source)[props.labelField] = null
  } else if (Array.isArray(chioseKey.value)) {
    unref(props.source)[props.labelField] = joinStr(
      chioseKey.value,
      (c: string) => deptCache[c].Name
    )
  } else {
    unref(props.source)[props.labelField] = deptCache[chioseKey.value].Name
  }
}
const reset = () => {
  comId = props.companyId ?? userStore.comId
  if (props.isChioseUnit) {
    checkstrictly.value = true
  } else {
    checkstrictly.value = !props.isChioseEnd
  }
  if (props.readonly) {
    if (chioseKey.value == null) {
      deptName.value = []
      return
    } else if (props.isMultiple && chioseKey.value.length !== 0) {
      loadName(chioseKey.value)
    } else if (props.isMultiple === false && chioseKey.value !== '0') {
      loadName([chioseKey.value])
    } else {
      deptName.value = []
    }
    refreshLabel()
  } else {
    deptName.value = []
    loadTree()
  }
}
const comName = async () => {
  return await GetName(comId)
}
const handleChange = () => {
  const e: deptSelectEvent = {
    isMultiple: props.isMultiple,
    companyId: comId,
    comName: comName,
    value: [],
    dept: deptCache
  }
  const val = chioseKey.value
  if (val != null) {
    if (props.isMultiple) {
      e.value = val as string[]
    } else if (val) {
      e.value.push(val as string)
    }
  }
  refreshLabel()
  emit('update:modelValue', val)
  emit('change', val, e)
}
watch(
  () => props.companyId,
  (val: string) => {
    if (props.readonly === false) {
      reset()
    }
  },
  {
    immediate: true
  }
)

watch(
  () => props.modelValue,
  (val: string) => {
    chioseKey.value = val
    if (props.readonly) {
      reset()
    }
  },
  {
    immediate: true
  }
)
watch(
  () => props.isUnit,
  (val: Boolean) => {
    loadTree()
  },
  {
    immediate: false
  }
)

watch(
  () => props.isDept,
  (val: Boolean) => {
    loadTree()
  },
  {
    immediate: false
  }
)
</script>

<template>
  <el-space v-if="readonly">
    <span v-for="i in deptName" :key="i">{{ i }}</span>
  </el-space>
  <el-tree-select
    v-else
    v-model="chioseKey"
    :data="depts"
    :default-expand-all="true"
    :highlight-current="true"
    :expand-on-click-node="false"
    :placeholder="placeholder"
    :props="defProps"
    :check-strictly="checkstrictly"
    :render-after-expand="props.renderAfterExpand"
    :show-checkbox="props.isMultiple"
    nodeKey="Id"
    :multiple="props.isMultiple"
    check-on-click-node
    :style="$attrs.style"
    :class="$attrs.class"
    :clearable="props.clearable"
    @change="handleChange"
  />
</template>
